package com.shenda.device.analysis;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import com.shenda.device.Constants;
import com.shenda.device.analysis.protocol.NewProtpcol;
import com.shenda.device.analysis.protocol.Protpcol;
import com.shenda.device.message.RespMsg_UploadStart;
import com.swak.rxtx.codec.Encodes;
import com.swak.utils.IOUtils;

/**
 * 数据文件的分析
 * 
 * @author lifeng
 * @date 2020年5月16日 下午7:01:34
 */
public abstract class BytesAnalysis implements Analysis, Encodes {

	/**
	 * 执行分析数据
	 */
	protected int doAnalysisData(InputStream inputStream) throws IOException {
		try {

			// 解析的协议
			Protpcol protpcol = this.newProtpcol();

			// 分析数据文件头部
			RespMsg_UploadStart head = this.doAnalysisData_head(protpcol, inputStream);

			// 分析数据文件数据
			return this.doAnalysisData_body(protpcol, inputStream, head);
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 分析文件头部
	 * 
	 * @param protpcol
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	protected RespMsg_UploadStart doAnalysisData_head(Protpcol protpcol, InputStream inputStream) throws IOException {

		// 读取头部
		byte[] head = protpcol.readHead(inputStream);

		// 解析头部数据
		RespMsg_UploadStart headMsg = (RespMsg_UploadStart) new RespMsg_UploadStart().parse(head);

		// 子类执行文件头分析
		this.doAnalysisHead(headMsg);

		// 返回识别到的头部信息
		return headMsg;
	}

	/**
	 * 分析实际数据
	 * 
	 * @param protpcol
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	protected int doAnalysisData_body(Protpcol protpcol, InputStream inputStream, RespMsg_UploadStart head)
			throws IOException {

		// 数据长度
		int total = head.getLength();

		// 数据库大小
		int blockSize = (total / Constants.iMinBlockSize);

		// 块数
		int frames = 0;

		// 循环取数据
		while (blockSize > 0) {

			// 读取一份数据
			byte[] data = protpcol.readData(inputStream);

			// 删除数据的头部
			data = Arrays.copyOfRange(data, 8, data.length);

			// 分析块数据
			frames += this.doAnalysisData_block(data);

			blockSize--;
		}
		// 返回帧数
		return frames;
	}

	/**
	 * 分析数据
	 * 
	 * @param data
	 * @throws IOException
	 */
	protected int doAnalysisData_block(byte[] data) throws IOException {

		// 一块数据
		ByteArrayInputStream bis = null;

		try {
			bis = new ByteArrayInputStream(data);

			// 可以读取的次数
			int recordSize = data.length / this.getRecordLength();

			// 当前行数
			int index = recordSize;

			// 读取一条记录
			while (index > 0) {

				// 读取一行
				byte[] record = new byte[this.getRecordLength()];
				bis.read(record);

				// 分析此行
				this.doAnalysisRecord(record);

				// 循环控制
				index--;
			}

			// 返回帧数
			return recordSize;
		} catch (Exception e) {
			return 0;
		} finally {
			IOUtils.closeQuietly(bis);
		}
	}

	/**
	 * 标准数据文件的头部长度
	 * 
	 * @return
	 */
	protected Protpcol newProtpcol() {
		return new NewProtpcol();
	}

	/**
	 * 转换为无符号的整形
	 * 
	 * @param bytes
	 * @return
	 * @throws IOException
	 */
	protected int toUInt16(byte[] bytes) {
		return ((bytes[1] & 0xFF) << 8) + (bytes[0] & 0xFF);
	}

	/**
	 * 获得一条记录的长度
	 * 
	 * @return
	 */
	protected abstract int getRecordLength();

	/**
	 * 初始化分析文件头
	 */
	protected abstract void doAnalysisHead(RespMsg_UploadStart head) throws IOException;

	/**
	 * 分析一行记录
	 * 
	 * @param data
	 * @throws IOException
	 */
	protected abstract void doAnalysisRecord(byte[] data) throws IOException;
}